package com.houger.license;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.PublicKey;
import java.time.LocalDate;

import static com.houger.license.HardwareFingerprint.signWithHmac;


@Slf4j
@Service
public class LicenseService {

    private final PublicKey publicKey;
    private final Path licenseFile = Paths.get("license.dat");

    public LicenseService(PublicKey publicKey) {
        this.publicKey = publicKey;
    }

    public boolean checkLicense() {
        if (isLicenseActivated()) {
            return checkExpirationDate();
        }
        return false;
    }

    private boolean isLicenseActivated() {
        if (!Files.exists(licenseFile)) {
            try {
                Files.writeString(licenseFile, "");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        try {
            String licenseData = Files.readString(licenseFile);
            return !licenseData.isEmpty();
        } catch (IOException e) {
            return false;
        }
    }

    private boolean checkExpirationDate() {
        try {
            log.debug("publicKey={}", publicKey.getFormat());
            String licenseData = Files.readString(licenseFile);
            Claims claims = Jwts.parser()
                .verifyWith(publicKey)
                .build()
                .parseSignedClaims(licenseData)
                .getPayload();
            // 增加指纹验证
            String storedFingerprint = claims.get("fingerprint", String.class);
            log.debug("指纹={}", storedFingerprint);
            if (!validateFingerprint(storedFingerprint)) {
                log.error("Fingerprint is not valid");
                return false;
            }
            LocalDate expireDate = LocalDate.parse(claims.get("expire", String.class));
            log.debug("expireDate={}", expireDate);
            return LocalDate.now().isBefore(expireDate);
        } catch (Exception e) {
            log.error("Exception={}", e.getMessage(), e);
            return false;
        }
    }


    // 新增方法获取当前设备指纹
    public String getCurrentFingerprint() {
        return HardwareFingerprint.getMachineId();
    }

    // 修改激活验证逻辑
    public boolean activate(String licenseKey) {
        try {
            String currentFingerprint = HardwareFingerprint.getMachineId();

            Claims claims = Jwts.parser()
                .verifyWith(publicKey)
                .build()
                .parseSignedClaims(licenseKey)
                .getPayload();

            // 验证指纹和有效期
            String storedFingerprint = claims.get("fingerprint", String.class);
            LocalDate expireDate = LocalDate.parse(claims.get("expire", String.class));

            if (!currentFingerprint.equals(storedFingerprint)) {
                return false;
            }
            // 在activate方法中增加验证
            if (!validateFingerprint(storedFingerprint)) {
                return false;
            }

            if (LocalDate.now().isAfter(expireDate)) {
                return false;
            }

            Files.writeString(licenseFile, licenseKey);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    private boolean validateFingerprint(String fingerprint) {
        try {
            String[] parts = fingerprint.split("\\|");
            if (parts.length != 2) return false;

            String data = parts[0];
            String signature = parts[1];

            // 验证HMAC签名
            String calculatedSign = signWithHmac(data);
            return calculatedSign.equals(signature);
        } catch (Exception e) {
            return false;
        }
    }


    public long getLastDay() {
        try {
            String licenseData = Files.readString(licenseFile);
            Claims claims = Jwts.parser()
                .verifyWith(publicKey)
                .build()
                .parseSignedClaims(licenseData)
                .getPayload();
            LocalDate expireDate = LocalDate.parse(claims.get("expire", String.class));
            log.debug("expireDate={}", expireDate);
            return expireDate.toEpochDay() - LocalDate.now().toEpochDay();
        } catch (Exception e) {
            log.error("Exception={}", e.getMessage(), e);
            return -1;
        }


    }

}